﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Surface.Core;
using Microsoft.Surface.Core.Manipulations;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


namespace Sublimation
{
    class MenuManipulator : GameComponent
    {
        protected List<MenuSurf> menuList = new List<MenuSurf>();
        protected List<Contact> prevTagList = new List<Contact>();
        protected List<Contact> curTagList = new List<Contact>();

        protected WorldPropertiesSurf worldProperties;
        protected Game game;
        public MenuManipulator(Game game, WorldPropertiesSurf worldProperties)
            : base(game)
        {
            this.game = game;
            Game.Components.Add(this);
            this.worldProperties = worldProperties;
        }
        private void CreateMenu(Contact hudContact)
        {
            MenuSurf hudMenu1 = new MenuSurf(worldProperties, hudContact);
            hudMenu1.Position = new Vector2(hudContact.CenterX, hudContact.CenterY);
            hudMenu1.Origin = new Vector2(0, 0);
            hudMenu1.Rotation = hudContact.Orientation;
            hudMenu1.AddItem("Add Tower");
            hudMenu1.AddItem("Add Tower");
            // align items according to rotation
            hudMenu1.AlignItems(hudMenu1.Rotation);
            menuList.Add(hudMenu1);
        }

        private bool ContainsContact(List<Contact> tagList, Contact contact)
        {
            bool contains = false;
            foreach (Contact curContact in tagList)
            {
                if (curContact.Tag.Byte.Value == contact.Tag.Byte.Value)
                {
                    contains = true;
                }
            }
            return contains;
        }

        #region overrided methods
        public override void Initialize()
        {
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            ReadOnlyContactCollection currentContacts = worldProperties.Contacts;

            foreach (Contact contact in currentContacts)
            {
                if (contact.IsTagRecognized)
                {
                    // add it to current tag list
                    curTagList.Add(contact);
                    if (menuList.Count != 0)
                    {
                        bool newHudCheck = true;

                        // update the menulist for new huds
                        foreach (MenuSurf aMenu in menuList)
                        {
                            if (aMenu.Contact.Tag.Byte.Value == contact.Tag.Byte.Value)
                            {
                                newHudCheck = false;
                            }
                        }
                        // if new hud is placed on the surface 
                        if (newHudCheck)
                        {
                            // create a new menu 
                            CreateMenu(contact);
                        }

                    }
                    // if it is the first hud contact
                    else
                    {
                        CreateMenu(contact);
                    }
                }
                /*
                 * Check finger contacts for each menu item 
                 */
                else if (contact.IsFingerRecognized)
                {
                    foreach (MenuSurf aMenu in menuList)
                    {
                        // if menu is on the surface, update
                        if (Game.Components.Contains(aMenu))
                        {
                            for (int i = 0; i < aMenu.MenuItemList.Count; i++)
                            {
                                MenuItemSurf aItem = (MenuItemSurf)aMenu.MenuItemList.ElementAt(i);
                                // if item hasn't got an associated contact
                                if (aItem.ItemContact == null)
                                {
                                    // make collision check
                                    if (aItem.Contains(contact))
                                    {
                                        aItem.ItemContact = contact;
                                        aItem.Position = new Vector2(contact.CenterX - aItem.Sprite.Width / 2
                                            , contact.CenterY - aItem.Sprite.Height / 2);
                                        aMenu.UpdateItemStatus(aItem);
                                    }
                                } 
                            }
                        }
                    }
                }
            } // end of currentContacts loop

            /* Find out of menu items and create towers */
            foreach (MenuSurf aMenu in menuList)
            {
                if (Game.Components.Contains(aMenu))
                {
                    List<MenuItem> menuItemList = aMenu.MenuItemList;
                    for (int i = 0; i < menuItemList.Count; i++)
                    {
                        MenuItemSurf aItem = (MenuItemSurf)menuItemList.ElementAt(i);
                        Contact itemContact = aItem.ItemContact;

                        if (itemContact != null)
                        {
                            Contact tempContact;
                            if (currentContacts.TryGetContactFromId(itemContact.Id, out tempContact))
                            {
                                // set the item position just at contact's center
                                aItem.Position = new Vector2(tempContact.CenterX - aItem.Sprite.Width / 2
                                    , tempContact.CenterY - aItem.Sprite.Height / 2);
                                aMenu.UpdateItemStatus(aItem);
                            }
                            else
                            {
                                aItem.ItemContact = null;
                                if (aItem.ItemStatus == MenuItemStatus.OutMenu)
                                {
                                    menuItemList.Remove(aItem);
                                    aItem.Kill();
                                    worldProperties.Players[0].addTower(aItem.Position.X, aItem.Position.Y);
                                }
                            }
                        }
                    }
                }
            }

            foreach (Contact tagContact in prevTagList)
            {
                // if the tag is removed
                if (!ContainsContact(curTagList, tagContact))
                {
                    // find the menu associated with that tag
                    for (int i = 0; i < menuList.Count; i++)
                    {
                        MenuSurf aMenu = menuList.ElementAt(i);
                        if (aMenu.Contact.Tag.Byte.Value == tagContact.Tag.Byte.Value)
                        {
                            // remove all menu items belong to the menu
                            foreach (MenuItem aItem in aMenu.MenuItemList)
                            {
                                aItem.Kill();
                            }
                            // remove the menu itself
                            aMenu.Kill();
                            menuList.Remove(aMenu);
                            curTagList.Remove(tagContact);
                        }
                    }
                }
            }
            foreach (Contact contact in curTagList)
            {
                // update each hud menu
                foreach (MenuSurf aMenu in menuList)
                {
                    if (aMenu.Contact.Tag.Byte.Value == contact.Tag.Byte.Value)
                    {
                        aMenu.Transform(contact);
                    }
                }
            }

            // save curTagList 
            prevTagList.Clear();
            prevTagList = new List<Contact>(curTagList);

            // clear the current tag list
            curTagList.Clear();
        }
        #endregion
    }
}
